package org.light.shiroauth;

import java.util.Set;
import java.util.TreeSet;

import org.light.core.LayoutComb;
import org.light.core.ReportComb;
import org.light.domain.ConfigFile;
import org.light.domain.Domain;
import org.light.domain.ManyToMany;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.easyuilayouts.widgets.Nav;
import org.light.exception.ValidateException;
import org.light.utils.DomainUtil;

public class SpringShiroXml extends ConfigFile{
	protected Domain userDomain;
	protected Domain roleDomain;
	protected Domain privilegeDomain;
	protected Nav nav;
	
	public SpringShiroXml(){
		super();
		this.standardName = "spring-shiro.xml";
		this.setPutInsideSrcAndClasses(true);
	}
	
	@Override
	public String generateConfigFileString() throws ValidateException {
		StatementList sList = new StatementList();
		sList.add(new Statement(1000L,0,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
		sList.add(new Statement(2000L,0,"<beans xmlns=\"http://www.springframework.org/schema/beans\""));
		sList.add(new Statement(3000L,0,"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""));
		sList.add(new Statement(4000L,0,"xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\">"));
		sList.add(new Statement(5000L,2,""));
		sList.add(new Statement(6000L,1,"<!--securityManager-->"));
		sList.add(new Statement(7000L,1,"<bean id=\"securityManager\" class=\"org.apache.shiro.web.mgt.DefaultWebSecurityManager\">"));
		sList.add(new Statement(8000L,2,"<property name=\"realm\" ref=\"userRealm\"/>"));
		sList.add(new Statement(8500L,0,"<property name=\"sessionManager\" ref=\"sessionManager\"/>"));

		sList.add(new Statement(9000L,1,"</bean>"));
		sList.add(new Statement(10000L,2,""));
		sList.add(new Statement(11000L,1,"<!--realm-->"));
		sList.add(new Statement(12000L,1,"<bean id=\"userRealm\" class=\""+this.userDomain.getPackageToken()+".shiro.UserRealm\">"));
		sList.add(new Statement(13000L,1,"</bean>"));
		sList.add(new Statement(14000L,1,""));
		
		sList.add(new Statement(14100L,1,"<!-- 会话管理器 -->"));
		sList.add(new Statement(14200L,1,"<bean id=\"sessionManager\""));
		sList.add(new Statement(14300L,2,"class=\""+this.userDomain.getPackageToken()+".shiro.MySessionManager\">"));
		sList.add(new Statement(14400L,1,"</bean>"));
		
		sList.add(new Statement(15000L,0,"<bean id=\"shiroFilter\" class=\"org.apache.shiro.spring.web.ShiroFilterFactoryBean\">"));
		sList.add(new Statement(16000L,2,"<property name=\"securityManager\" ref=\"securityManager\"/>"));
		sList.add(new Statement(17000L,2,"<property name=\"loginUrl\" value=\"/login/index.html\"/>"));
		sList.add(new Statement(18000L,2,"<property name=\"unauthorizedUrl\" value=\"/login/noauth.html\"/>"));
		sList.add(new Statement(19000L,2,"<property name=\"filterChainDefinitions\">"));
		sList.add(new Statement(20000L,3,"<value>"));
		sList.add(new Statement(21000L,4,"/index.html = anon"));
		sList.add(new Statement(22000L,4,"/login/** = anon"));
		sList.add(new Statement(23000L,4,"/js/** = anon"));
		sList.add(new Statement(24000L,4,"/easyui/** = anon"));
		sList.add(new Statement(24500L,4,"/echarts/** = anon"));
		sList.add(new Statement(25000L,4,"/images/** = anon"));
		sList.add(new Statement(25500L,4,"/uploadjs/** = anon"));
		sList.add(new Statement(26000L,4,"/"+this.userDomain.getControllerPackagePrefix()+"login"+this.userDomain.getControllerNamingSuffix()+"/** = anon"));
		
		sList.add(new Statement(28000L,4,"/"+this.userDomain.getControllerPackagePrefix()+"*"+this.userDomain.getControllerNamingSuffix()+"/find* = authc"));
		sList.add(new Statement(29000L,4,"/"+this.userDomain.getControllerPackagePrefix()+"*"+this.userDomain.getControllerNamingSuffix()+"/listActive* = authc"));
		sList.add(new Statement(29100L,4,"/"+this.userDomain.getControllerPackagePrefix()+"profile"+this.userDomain.getControllerNamingSuffix()+"/* = authc"));
		sList.add(new Statement(29200L,4,"/pages/profile.html = authc"));
		
		sList.add(new Statement(30000L,4,"/"+this.roleDomain.getControllerPackagePrefix()+this.roleDomain.getLowerFirstDomainName()+this.roleDomain.getControllerNamingSuffix()+"/* = roles[admin]"));
		sList.add(new Statement(31000L,4,"/"+this.privilegeDomain.getControllerPackagePrefix()+this.privilegeDomain.getLowerFirstDomainName()+this.privilegeDomain.getControllerNamingSuffix()+"/* = roles[admin]"));
		sList.add(new Statement(32000L,4,"/"+this.userDomain.getControllerPackagePrefix()+this.userDomain.getLowerFirstDomainName()+this.userDomain.getControllerNamingSuffix()+"/* = roles[admin]"));
		
		sList.add(new Statement(33000L,4,"/pages/"+this.privilegeDomain.getPlural().toLowerCase()+".html = roles[admin]"));
		sList.add(new Statement(34000L,4,"/pages/"+this.roleDomain.getPlural().toLowerCase()+".html = roles[admin]"));
		sList.add(new Statement(35000L,4,"/pages/"+this.userDomain.getPlural().toLowerCase()+".html = roles[admin]"));	
		//sList.add(new Statement(36000L,4,"/pages/* = authc"));
		
		long serial = 37000L;
		Set<Domain> adminDomains = new TreeSet<>();
		adminDomains.add(this.userDomain);
		adminDomains.add(this.roleDomain);
		adminDomains.add(this.privilegeDomain);
		if (this.nav.getDomains()!=null&&this.nav.getDomains().size()>0) {
			Set<Domain> myDomains = this.nav.getDomains();
			for (Domain d:myDomains) {
				if (!DomainUtil.inDomainSet(d,adminDomains)) {
					sList.add(new Statement(serial,4,"/pages/"+d.getPlural().toLowerCase()+".html = perms["+d.getStandardName()+"]"));
					sList.add(new Statement(serial+1000L,4,"/"+d.getControllerPackagePrefix()+d.getLowerFirstDomainName()+d.getControllerNamingSuffix()+"/** = perms["+d.getStandardName()+"]"));
					serial += 2000L;
				}
			}
		}
		
		if (this.nav.getMtms()!=null&&this.nav.getMtms().size()>0) {
			for (ManyToMany mtm:this.nav.getMtms()) {
				if (!DomainUtil.inDomainSet(mtm.getMaster(), adminDomains)) {
					sList.add(new Statement(serial,4,"/pages/"+("Link"+mtm.getMaster().getStandardName()+mtm.getSlaveAlias()).toLowerCase()+".html = perms["+mtm.getMaster().getStandardName()+"]"));
				}else {
					sList.add(new Statement(serial,4,"/pages/"+("Link"+mtm.getMaster().getStandardName()+mtm.getSlaveAlias()).toLowerCase()+".html = roles[admin]"));
				}
				serial += 2000L;
			}
		}
		if (this.nav.getLayouts()!=null&&this.nav.getLayouts().size()>0) {
			for (LayoutComb lc:this.nav.getLayouts()) {
				Set<Domain> mydomains = lc.getDomains();
				if (DomainUtil.memberInDomainSet(adminDomains,mydomains)) {
					sList.add(new Statement(serial,4,"/pages/"+lc.getStandardName().toLowerCase()+".html = roles[admin]"));
				}else{
					sList.add(new Statement(serial,4,"/pages/"+lc.getStandardName().toLowerCase()+".html = perms["+lc.getDomainNamesStr()+"]"));
				}
				serial += 2000L;
			}
		}
		if (this.nav.getReports()!=null&&this.nav.getReports().size()>0) {
			for (ReportComb rc:this.nav.getReports()) {
				Set<Domain> mydomains = rc.getDomains();
				if (DomainUtil.memberInDomainSet(adminDomains,mydomains)) {
					sList.add(new Statement(serial,4,"/pages/"+rc.getStandardName().toLowerCase()+".html = roles[admin]"));
				}else{
					sList.add(new Statement(serial,4,"/pages/"+rc.getStandardName().toLowerCase()+".html = perms["+rc.getDomainNamesStr()+"]"));
				}
				serial += 2000L;
			}
		}
		
		sList.add(new Statement(serial+30000L,3,"</value>"));
		sList.add(new Statement(serial+31000L,2,"</property>"));
		sList.add(new Statement(serial+32000L,1,"</bean>"));
		sList.add(new Statement(serial+33000L,1,""));
		sList.add(new Statement(serial+34000L,1,""));
		sList.add(new Statement(serial+35000L,0,""));
		sList.add(new Statement(serial+36000L,0,"</beans>"));

		return sList.getContent();
	}

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
	}

	public Domain getRoleDomain() {
		return roleDomain;
	}

	public void setRoleDomain(Domain roleDomain) {
		this.roleDomain = roleDomain;
	}

	public Domain getPrivilegeDomain() {
		return privilegeDomain;
	}

	public void setPrivilegeDomain(Domain privilegeDomain) {
		this.privilegeDomain = privilegeDomain;
	}

	public Nav getNav() {
		return nav;
	}

	public void setNav(Nav nav) {
		this.nav = nav;
	}
}
